﻿#region zh-CHS 2006 - 2007 DemoSoft 团队 | en 2006 - 2007 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the G.O.S.E(Game Online Server Engine) for .NET.
//
//                 2006-2007 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Demo_G.O.S.E.ServerEngine.Util;
using Demo_G.O.S.E.ServerEngine.Timer;
using Demo_G.O.S.E.ServerEngine.World;
using Demo_G.O.S.E.ServerEngine.Server;
using Demo_G.O.S.E.ServerEngine.Common;
#endregion

namespace Demo_G.O.S.E.ServerEngine.Network
{
    /// <summary>
    /// 数据信息包抽取处理
    /// </summary>
    [MultiThreadedSupportgAttribute( "当前的类所有成员都可锁定,支持多线程操作" )]
    public class MessagePump
    {
        #region zh-CHS 共有属性 | en Public Properties

        #region zh-CHS Listeners属性 | en Listeners Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 多个监听的端口
        /// </summary>
        private Listener[] m_Listeners = new Listener[0];
        #endregion
        /// <summary>
        /// 监听的端口
        /// </summary>
        public Listener[] Listeners
        {
            get { return m_Listeners; }
        }

        #region zh-CHS 共有方法 | en Public Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 只锁定添加操作(因为是数组，其它的地方就可以不用锁定的)
        /// </summary>
        private ReaderWriterLockSlim m_OnlyLockAddListener = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 添加多个监听端口的数据传过来
        /// </summary>
        /// <param name="listener"></param>
        public void AddListener( Listener listener )
        {
            ReaderWriterLockSlimEx.EnterWriteLock( m_OnlyLockAddListener );
            {
                // 创建新的Listener数组,添加数据,交换数组数据,不需要锁定,没有引用时自动会回收数据
                Listener[] tempListener = new Listener[m_Listeners.Length + 1];

                for ( int iIndex = 0; iIndex < m_Listeners.Length; ++iIndex )
                    tempListener[iIndex] = m_Listeners[iIndex];

                tempListener[m_Listeners.Length] = listener;
                listener.SetBaseWorld( m_BaseWorld );

                m_Listeners = tempListener;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_OnlyLockAddListener );
        }

        #endregion

        #endregion

        #region zh-CHS Connecters属性 | en Connecters Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 多个监听的端口
        /// </summary>
        private Connecter[] m_Connecters = new Connecter[0];
        #endregion
        /// <summary>
        /// 连接的端口
        /// </summary>
        public Connecter[] Connecters
        {
            get { return m_Connecters; }
        }

        #region zh-CHS 共有方法 | en Public Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 只锁定添加操作(因为是数组，其它的地方就可以不用锁定的)
        /// </summary>
        private ReaderWriterLockSlim m_OnlyLockAddConnecter = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 添加多个连接端口的数据传过来
        /// </summary>
        public void AddConnecter( Connecter connecter )
        {
            ReaderWriterLockSlimEx.EnterWriteLock( m_OnlyLockAddConnecter );
            {
                // 创建新的Listener数组,添加数据,交换数组数据,不需要锁定,没有引用时自动会回收数据
                Connecter[] tempConnecter = new Connecter[m_Connecters.Length + 1];

                for ( int iIndex = 0; iIndex < m_Connecters.Length; ++iIndex )
                    tempConnecter[iIndex] = m_Connecters[iIndex];

                tempConnecter[m_Connecters.Length] = connecter;
                connecter.SetBaseWorld( m_BaseWorld );

                m_Connecters = tempConnecter;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_OnlyLockAddConnecter );
        }
        #endregion

        #endregion

        #region zh-CHS BaseWorld属性 | en BaseWorld Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 管理当前的世界服务
        /// </summary>
        private BaseWorld m_BaseWorld = null;
        #endregion
        /// <summary>
        /// 管理当前的世界服务
        /// </summary>
        public BaseWorld BaseWorld
        {
            get { return m_BaseWorld; }
        }

        #region zh-CHS 内部方法 | en Internal Methods
        /// <summary>
        /// 设置管理当前的世界服务
        /// </summary>
        /// <param name="baseWorld"></param>
        internal void SetBaseWorld( BaseWorld baseWorld )
        {
            m_BaseWorld = baseWorld;

            // 重新设置Listener数据的BaseWorld
            Listener[] listeners = m_Listeners;
            foreach ( Listener listener in listeners )
                listener.SetBaseWorld( m_BaseWorld );

            // 重新设置Connecter数据的BaseWorld
            Connecter[] connecters = m_Connecters;
            foreach ( Connecter connecter in connecters )
                connecter.SetBaseWorld( m_BaseWorld );
        }
        #endregion

        #endregion

        #endregion

        #region zh-CHS 内部方法 | en Internal Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 当前需要处理的NetState集合
        /// </summary>
        private Queue<NetState> m_NetStateQueue = new Queue<NetState>();
        /// <summary>
        /// 锁定的类
        /// </summary>
        private ReaderWriterLockSlim m_LockNetStateQueue = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 时间片的处理
        /// </summary>
        internal void Slice()
        {
            // 检查有多少新的连接用户
            CheckListener();

            // 检查有多少新的连出用户
            CheckConnecter();

            NetState[] netStateArray = null;

            // 转换成数组减少lock处理的时间
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockNetStateQueue );
            do
            {
                if ( m_NetStateQueue.Count == 0 )
                    break;

                netStateArray = m_NetStateQueue.ToArray();

                // 清空数据,下面处理这些数据
                m_NetStateQueue.Clear();
            } while ( false );
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockNetStateQueue );

            // 如果没有需要处理的数据则返回
            if ( netStateArray == null )
                return;

            // 处理接收到的数据
            foreach ( NetState netState in netStateArray )
            {
                if ( netState.Running )
                {
                    ReceiveQueue receiveQueueBuffer = netState.ReceiveBuffer;
                    if ( receiveQueueBuffer == null )
                    {
                        Debug.WriteLine( "MessagePump.Slice(...) - byteQueueBuffer == null error!" );
                        continue;
                    }

                    // 检测是否已经在处理数据中,防止多线程中多次处理里面的数据
                    if ( receiveQueueBuffer.Lock() == false )
                        continue;

                    OnProcessReceive( netState );

                    // 已经结束处理
                    receiveQueueBuffer.Free();
                }

                // 表示当前已不再处理列表中(减少处理列表的长度)
                netState.OutProcessQueue();

                // 再次检测是否还有没处理完接受到的数据,如果有,再次进入处理列表(可能是半包或还有没来得急处理的数据,等待数据的完整,1秒以后再次处理,仅调用一次)
                if ( netState.Running )
                {
                    if ( netState.ReceiveBuffer.Length > 0 )
                        TimeSlice.StartTimeSlice( TimeSpan.FromSeconds( 1.0 ), new TimeSliceStateCallback<NetState>( OnceAgainReceive ), netState );
                }
            }
        }

        #region zh-CHS 再次进入处理数据的时间片回调函数 | en TimeSlice
        /// <summary>
        /// 再次处理没处理完全的数据(仅调用一次)
        /// </summary>
        /// <param name="netState"></param>
        private void OnceAgainReceive( NetState netState )
        {
            if ( netState.Running )
            {
                if ( netState.ReceiveBuffer.Length > 0 )
                    OnReceive( netState );
            }
        }
        #endregion

        /// <summary>
        /// 网络上面有数据过来
        /// </summary>
        /// <param name="netState"></param>
        internal void OnReceive( NetState netState )
        {
            if ( netState.InProcessQueue()  == false )
                return;
           
            // 表示当前已加入在处理列表中(减少处理列表的长度)

            ReaderWriterLockSlimEx.EnterWriteLock( m_LockNetStateQueue );
            {
                m_NetStateQueue.Enqueue( netState );
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockNetStateQueue );

            // 有数据过来需要发送全局信号处理数据包
            if ( m_BaseWorld != null )
                m_BaseWorld.SetWorldSignal();
            else
                Debug.WriteLine( "MessagePump.OnReceive(...) - m_BaseWorld == null error!" );
        }
        #endregion

        #region zh-CHS 私有方法 | en Private Methods
        /// <summary>
        /// 检查是否有新的客户端接过来
        /// </summary>
        private void CheckListener()
        {
            foreach ( Listener listener in m_Listeners )
            {
                // 获取连接的客户端
                ClientSocketHandler[] acceptedHandler = listener.Slice();

                foreach ( ClientSocketHandler clientSocketHandler in acceptedHandler )
                {
                    if ( clientSocketHandler == null )
                        continue;

                    // 把连接过来的客户端放置入NetState中,当前的实例会保存在NetState.Instances中
                    NetState netState = new NetState( clientSocketHandler, this );
                    if ( netState == null )
                    {
                        Debug.WriteLine( "MessagePump.CheckListener(...) - netState == null error!" );
                        continue;
                    }

                    OnNetStateInit( netState );

                    netState.Start();
                }
            }
        }

        /// <summary>
        /// 检查是否有新的客户端接出来
        /// </summary>
        private void CheckConnecter()
        {
            foreach ( Connecter connecter in m_Connecters )
            {
                // 检查是否已经处理过
                if ( connecter.IsSlice )
                    continue;

                // 获取连接出去的客户端
                ClientSocketHandler clientSocketHandler = connecter.Slice();
                if ( clientSocketHandler != null )
                {
                    // 把连接出来的客户端放置入NetState中,当前的实例会保存在NetState.Instances中
                    NetState netState = new NetState( clientSocketHandler, this );
                    if ( netState == null )
                    {
                        Debug.WriteLine( "MessagePump.CheckConnecter(...) - netState == null error!" );
                        continue;
                    }

                    OnNetStateInit( netState );

                    netState.Start();
                }
            }
        }
        #endregion

        #region zh-CHS 内部的事件处理函数 | en Internal Event Handlers
        /// <summary>
        /// 处理接收到的数据
        /// </summary>
        /// <param name="netState"></param>
        internal void OnProcessReceive( NetState netState )
        {
            EventHandler<NetStateEventArgs> tempThreadEventProcessReceive = m_ThreadEventProcessReceive;
            if ( tempThreadEventProcessReceive != null )
            {
                NetStateEventArgs netStateEventArgs = new NetStateEventArgs( netState );
                tempThreadEventProcessReceive( this, netStateEventArgs );
            }
        }

        /// <summary>
        /// 创建了新的NetState需要的初始化
        /// </summary>
        internal void OnNetStateInit( NetState newNetState )
        {
            EventHandler<NetStateInitEventArgs> tempThreadEventNetStateCreate = m_ThreadEventNetStateCreate;
            if ( tempThreadEventNetStateCreate != null )
            {
                NetStateInitEventArgs netStateInitEventArgs = new NetStateInitEventArgs( newNetState );
                tempThreadEventNetStateCreate( this, netStateInitEventArgs );
            }
        }
        #endregion

        #region zh-CHS 共有事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<NetStateEventArgs> m_ThreadEventProcessReceive;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventProcessReceive = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 数据处理事件
        /// </summary>
        [MultiThreadedWarningAttribute( "此处会在不同的线程内回调:(多线程)警告!" )]
        public event EventHandler<NetStateEventArgs> ThreadEventProcessReceive
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventProcessReceive );
                {
                    m_ThreadEventProcessReceive += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventProcessReceive );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventProcessReceive );
                {
                    m_ThreadEventProcessReceive -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventProcessReceive );
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<NetStateInitEventArgs> m_ThreadEventNetStateCreate;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventNetStateCreate = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 当创建一个新的NetState时的回调
        /// </summary>
        [MultiThreadedWarningAttribute( "此处会在不同的线程内回调:(多线程)警告!" )]
        public event EventHandler<NetStateInitEventArgs> ThreadEventNetStateCreate
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventNetStateCreate );
                {
                    m_ThreadEventNetStateCreate += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventNetStateCreate );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventNetStateCreate );
                {
                    m_ThreadEventNetStateCreate -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventNetStateCreate );
            }
        }
        #endregion
    }
}
#endregion
